// value.h
// Value, a generic container for any Ripe datatype.
//
// Copyright (C) 2008  Maksim Sipos <msipos@mailc.net>
//
// This file is a part of the Ripe language project.
//
// Ripe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#ifndef R_VALUE_HPP
#define R_VALUE_HPP

#include "util/standard.hpp"

namespace Ripe {
  typedef uintptr_t Value;

  // Bits are:         Value is:
  // 0000....0100      True
  // 0000....0000      False
  // 0000....1100      Nil
  // ..........00      Reference
  // ...........1      Integer
  // ..........10      Float

  // The R_VALUE_MASK is the least two significant bits in a Value. If the
  // Value is a reference (pointer) those will both be 0, since on a 32-bit
  // machine allocated memory is at least aligned to 4-bytes.
  #define R_VALUE_MASK 0x00000003

  // Not of R_VALUE_MASK
  #define R_VALUE_NOT_MASK 0xFFFFFFFC

  // The R_VALUE_LSB_MASK is the last significant bit in a Value. If the
  // Value is an integer, the LSB is always 1. The integer is then "fitted"
  // into the remaining 31 bits.
  #define R_VALUE_LSB_MASK 1

  // 31st bit is the second to the most significant bit in a Value. It is used
  // when converting Value to a signed integer.
  #define R_VALUE_31 0x40000000

  // Most significant bit is used in operations of converting a signed integer
  // to a Value.
  #define R_VALUE_MSB 0x80000000

  // Inverted version of the MSB:
  #define R_VALUE_NOT_MSB 0x7FFFFFFF

  // Direct values:
  #define R_VALUE_TRUE  4
  #define R_VALUE_FALSE 0
  #define R_VALUE_NIL   12

  static inline bool val_is_reference(Value v){
    if (v < 13) return false;
    return (v & R_VALUE_MASK) == 0;
  }

  static inline bool val_is_int(Value v){
    return (v & R_VALUE_LSB_MASK) == R_VALUE_LSB_MASK;
  }

  static inline bool val_is_float(Value v){
    return (v & R_VALUE_MASK) == 2;
  }

  // This returns a 31-bit signed integer from a given Value. Thus, in 32-bit
  // integer the most significant-bit (one right after the sign bit) will
  // always be equal to the sign bit.
  static inline int32_t val_int(Value v){
    // Logically shift right to fill up the LSB
    v >>= 1;

    // Make the sign bit equal to MSB
    v |= ((v & R_VALUE_31) << 1);

    return (int32_t) v;
  }

  // Return a floating point from the given Value. Return floating point value
  // is missing 2 bits of precision in the mantissa. (30-bit floating point).
  static inline float val_float(Value v){
    return (float) (R_VALUE_NOT_MASK & v);
  }

  // Packs a 31-bit signed integer into a Value. The most-significant bit of
  // the signed value is lost (not the sign bit).
  static inline Value val_from(int32_t i){
    Value t = (Value) i;

    // Get rid of 31-st bit, shift left and make the LSB 1.
    return ((t & R_VALUE_MSB) | ((t << 1) & R_VALUE_NOT_MSB))
     | R_VALUE_LSB_MASK ;
  }
  
  // Return true if two values are termed equal. For direct values, this is
  // a strict equality. For references, this is the case for all object
  // except strings and tuples.
  bool val_equal(Value v1, Value v2);
}

#endif // R_VALUE_HPP
